package com.zero2oneblog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zero2oneblog.constant.RoleType;
import com.zero2oneblog.entity.Role;
import com.zero2oneblog.entity.UserInfo;
import com.zero2oneblog.entity.UserRole;
import com.zero2oneblog.handler.exception.RoleNotFoundException;
import com.zero2oneblog.handler.exception.UserNameAlreadyExistException;
import com.zero2oneblog.mapper.RoleMapper;
import com.zero2oneblog.mapper.UserInfoMapper;
import com.zero2oneblog.mapper.UserRoleMapper;
import com.zero2oneblog.service.IUserInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zero2oneblog.service.IUserRoleService;
import com.zero2oneblog.service.IUserService;
import com.zero2oneblog.vo.UserInfoRegisterRequestVO;
//import com.zero2oneblog.vo.UserRegisterRequestVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import com.google.common.collect.ImmutableMap;

import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author liangjiu
 * @since 2024-01-03
 */
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements IUserInfoService {

    public static final String USERNAME = "username:";

    @Autowired
    private PasswordEncoder bCryptPasswordEncoder;
    /*
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    这个错误通常是由于没有在Spring的上下文中注册BCryptPasswordEncoder的Bean引起的。BCryptPasswordEncoder是Spring Security中常用的密码编码器，但它需要在配置中进行显式注册。
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

        @Configuration
        public class SecurityConfig {

            @Bean
            public BCryptPasswordEncoder bCryptPasswordEncoder() {
                return new BCryptPasswordEncoder();
            }

            // 其他配置...
}

     */
//    private final BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private IUserRoleService userRoleService;

//    @Autowired
//    private IUserInfoService userInfoService; //循环依赖

//    @Autowired
//    private UserInfoServiceImpl userInfoService; //循环依赖

//    private UserInfoServiceImpl userInfoService;
//
//    @Autowired
//    public void setUserInfoService(UserInfoServiceImpl userInfoService) {
//        this.userInfoService = userInfoService;
//    }


//    public UserInfoServiceImpl(BCryptPasswordEncoder bCryptPasswordEncoder) {
//        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
//    }

    @Override
    public List<UserInfo> userInfoList() {
        return userInfoMapper.selectList(null);
    }

//    @Override
//    public void save(UserInfoRegisterRequestVO userInfoRegisterRequestVO) {
//        ensureUserNameNotExist(userInfoRegisterRequestVO.getUserName()); //先确保用户名有没有重复
//        UserInfo userinfo = userInfoRegisterRequestVO.toUser();
//
//        userinfo.setPassword(bCryptPasswordEncoder.encode(userInfoRegisterRequestVO.getPassword())); //密码加密
//
//        userInfoService.save(userinfo); //这里不先保存，后面user_role表的id是一个负数
//
//        LambdaQueryWrapper<Role> queryWrapper = Wrappers.lambdaQuery();
//        queryWrapper.eq(Role::getRole, RoleType.USER.getName()); //既然RoleType里已经有定义，为什么还要查数据库呢。
//        Role role = roleMapper.selectOne(queryWrapper);
//        if(role==null){
//            throw new RoleNotFoundException(ImmutableMap.of("roleName", RoleType.USER.getName()));
//        }
//        else {
//            userRoleService.save(new UserRole(userinfo,role));
//        }
//
//
////        Role studentRole = roleMapper.selectOne()
////                roleRepository.findByName(RoleType.USER.getName()).orElseThrow(() -> new RoleNotFoundException(ImmutableMap.of("roleName", RoleType.USER.getName())));
//
//
//    }


    private void ensureUserNameNotExist(String userName) {
//        boolean exist = userRepository.findByUserName(userName).isPresent();
//        boolean exist = userInfoMapper.
        LambdaQueryWrapper<UserInfo> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(UserInfo::getUsername, userName);

        int count = Math.toIntExact(userInfoMapper.selectCount(queryWrapper));
        if(count>0){  // 如果 count 大于 0，表示存在重复记录
//            throw new UserNameAlreadyExistException()
            throw new UserNameAlreadyExistException(ImmutableMap.of(USERNAME, userName));
            /*
            这段代码使用了 ImmutableMap.of 创建一个不可变的 Map，其中键为 USERNAME，对应的值是 userName。这个地方的目的可能是在 UserNameAlreadyExistException 异常中传递额外的信息，提供已经存在的用户名信息以便后续处理或记录。
             */
//            throw new UserNameAlreadyExistException(ErrorCode.USER_NAME_ALREADY_EXIST);
        }

        // 查询满足条件的记录
//        UserInfo user = userInfoMapper.selectOne(queryWrapper); //MyBatis Plus 提供了 selectOne 方法，可以根据条件查询匹配的单条记录。
//        if( user != null ){ //不为空则表示有重复

        /*
        selectOne 和 selectCount 这两个方法的性能取决于具体的数据库和表结构，以及查询条件等因素。一般来说，无法简单地断定哪一个更快，因为它们用于不同的目的。

        selectOne 用于查询单条记录。如果你只关心是否有记录，并且只需要获取一条记录，那么使用 selectOne 可能更为合适，因为它会在找到一条记录后就停止查询，不会继续查找其他匹配的记录。

        selectCount 用于统计满足条件的记录数量，但不会获取实际的记录内容。如果你只关心记录的数量而不需要实际的记录数据，或者只是为了检查是否有匹配的记录，那么使用 selectCount 可能更为高效，因为它不需要返回实际记录数据。

        在实际应用中，建议根据具体的需求和场景选择使用 selectOne 或 selectCount。在大多数情况下，两者性能的差异可能不会很大。在性能要求较高的场景，可以通过具体的性能测试来确定哪个方法更适合你的业务。
         */
//
//        }




    }
}
